package org.joyflow.core.meta;

import org.springframework.util.CollectionUtils;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

public class Database {
    public static final String CR = System.lineSeparator();
    private DbMeta dbMeta;
    private Connection connection;
    public Database (DbMeta dbMeta) {
        this.dbMeta = dbMeta;
    }
    public DbMeta getDbMeta() {
        return dbMeta;
    }

    public void connect() {
        connectUsingClass(dbMeta.getDriverClass());

    }

    private void connectUsingClass(String driverClass) {

        try {
            synchronized (DriverManager.class) {
                Class.forName( driverClass );
            }
            String url = dbMeta.getURL();
            String username = dbMeta.getUsername();
            String password = dbMeta.getPassword();
            connection = DriverManager.getConnection(url, username, password);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public void disconnect() {
        if (connection != null) {
            try {
                connection.close();
            } catch (SQLException e) {
                throw new RuntimeException(e);
            }
        }
    }

    public String getCreateTableStatement(String tableName, List<FieldDefinition> fields) {
        StringBuilder retVal = new StringBuilder();
        retVal.append("create table ");
        retVal.append(tableName).append(CR);
        retVal.append("(").append(CR);
        List<FieldDefinition> keyFields = new ArrayList<>();
        for (int i = 0; i < fields.size(); i++) {
            if(i > 0){
                retVal.append(", ");
                retVal.append(CR);
                retVal.append("  ");
            }else {
                retVal.append("  ");
            }
            FieldDefinition fieldDefinition = fields.get(i);
            retVal.append(dbMeta.getFieldDefinition(fieldDefinition));
            if (fieldDefinition.isPrimaryKey()) {
                keyFields.add(fieldDefinition);
            }
        }
        if (!keyFields.isEmpty()) {
            retVal.append(", ");
            retVal.append(CR);
            retVal.append("  ");
            retVal.append("primary key (");
            for (int i = 0; i < keyFields.size(); i++) {
                if (i > 0) {
                    retVal.append(", ");
                }
                retVal.append(keyFields.get(i).getName());
            }
            retVal.append(")").append(CR);
        }
        retVal.append(")").append(CR);

        return retVal.toString();
    }

    public void execStatements(List<String> statements) {
        if (!CollectionUtils.isEmpty(statements)) {
            connect();
            for (String sql : statements) {
                try {
                    Statement statement = connection.createStatement();
                    statement.execute(sql);
                } catch (SQLException e) {
                    throw new RuntimeException(e);
                }
            }
            disconnect();
        }
    }

    public String getSelectStatement(String tableName, List<FieldDefinition> fieldDefinitions) {
        StringBuilder retVal = new StringBuilder();
        retVal.append("select ");
        retVal.append(CR);
        for (int i = 0; i < fieldDefinitions.size(); i++) {
            if (i > 0) {
                retVal.append(", ");
                retVal.append(CR);
                retVal.append("  ");
            } else {
                retVal.append("  ");
            }
            retVal.append(fieldDefinitions.get(i).getName());
        }
        retVal.append(" ");
        retVal.append(CR);
        retVal.append("from ");
        retVal.append(tableName);
        return retVal.toString();
    }

    public String getPageSelectStatement(String tableName, List<FieldDefinition> fieldDefinitions, int pageIndex, int pageSize) {
        StringBuilder retVal = new StringBuilder();
        retVal.append("select ");
        retVal.append(CR);
        for (int i = 0; i < fieldDefinitions.size(); i++) {
            if (i > 0) {
                retVal.append(", ");
                retVal.append(CR);
                retVal.append("  ");
            } else {
                retVal.append("  ");
            }
            retVal.append(fieldDefinitions.get(i).getName());
        }
        retVal.append(" ");
        retVal.append(CR);
        retVal.append("from ");
        retVal.append(tableName);
        retVal.append(" ");
        retVal.append("limit ").append(pageSize).append(" offset ").append((pageIndex - 1) * pageSize);
        return retVal.toString();
    }

    public String getCountStatement(String tableName) {
        StringBuilder retVal = new StringBuilder();
        retVal.append("select count(*) ");
        retVal.append(CR);
        retVal.append("from ");
        retVal.append(tableName);
        return retVal.toString();
    }

}
